home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Arashi 1.1.1 / source code / Game Source / jam src / STFuseBalls.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-01  |  9.6 KB  |  370 lines  |  [TEXT/KAHL]

  1. /*/
  2.      Project Arashi: STFuseBalls.c
  3.      Major release: Version 1.1d2, 9/5/95
  4.  
  5.      Last modification: Tuesday, June 1, 1993, 22:07
  6.      Created: Sunday, January 13, 1991, 14:28
  7.  
  8.      Copyright © 1991-1993, Juri Munkki
  9. /*/
  10.  
  11. #include "VA.h"
  12. #include "STORM.h"
  13. #include "STFloatingScores.h"
  14. #include "PlayOptions.h"
  15.  
  16. #define    MAXFUSEBALLS        20
  17. #define    FUSESTARCOLOR        0
  18. #define    WARPRANGE            ((DEPTH+DEPTH/5)<<4)
  19. #define    MAXWARP                (DEPTH<<3)
  20. #define    WARPSPEED            50
  21. #define    WARPPROB            (ThisLevel.fuWarpP)
  22. #define    WARPANGER            (ThisLevel.fuPlayerPlus)
  23. #define    MAXLEVELSPEED        3
  24. #define    LANEDIVISIONS        256
  25. #define    MAXLANESPEED        (LANEDIVISIONS/8)
  26. #define    ROTATIONSPEED        2    /*(ANGLES/2-1)*/
  27. #define    FUSEDANGERLEVEL        1
  28. /*#define    ZIMMER_WARP*/
  29.  
  30. extern    Player    Hero;
  31.  
  32. typedef    struct
  33. {
  34.     int        activeflag;
  35.     int        mode;
  36.     int        lane;
  37.     int        sublane;
  38.     int        level;
  39.     int        warplevel;
  40.     int        lanespeed;
  41.     int        levelspeed;
  42.     int        rotation;
  43. }    FuseBall;
  44.  
  45. /*    FuseBall movement modes:    */
  46. enum    {    Waiting=0,Brownian, Warp, Edge    };
  47.  
  48. FuseBall    *Balls;
  49. int            NumBalls;
  50.  
  51. void    CreateNewBall()
  52. {
  53.     register    FuseBall    *fbp;
  54.     
  55.     if(NumBalls<MAXFUSEBALLS)
  56.     {    fbp=Balls;
  57.         NumBalls++;
  58.         while(fbp->activeflag)
  59.         {    fbp++;
  60.         }
  61.         fbp->mode=Waiting;
  62.         fbp->level=DEPTH<<4;
  63.         fbp->rotation=0;
  64.         fbp->activeflag=-1;
  65.         StarApproach(&(fbp->mode),FUSESTARCOLOR);
  66.     }
  67. }
  68. /*
  69. >>    This routine creates two fuseballs from a destroyed
  70. >>    tanker.
  71. */
  72. void    CreateSplitFuseBalls(lane,level)
  73. int        lane,level;
  74. {
  75.     register    int            i;
  76.     register    FuseBall    *theball;
  77.             
  78.     for(i=0;i<2;i++)
  79.     {    if(NumBalls<MAXFUSEBALLS)
  80.         {    theball=Balls;
  81.             while(theball->activeflag)
  82.             {    theball++;
  83.             }
  84.             theball->mode=Brownian;
  85.             theball->lane= lane;
  86.             theball->activeflag= 1;
  87.             theball->level=level<<4;
  88.             theball->sublane= i ? (LANEDIVISIONS-LANEDIVISIONS/4) : (LANEDIVISIONS/4);
  89.             theball->lanespeed= i ? (MAXLANESPEED) : (-MAXLANESPEED);
  90.             theball->levelspeed=0;
  91.             theball->rotation=i ? 0 : (ANGLES/3);
  92.  
  93.             NumBalls++;
  94.         }
  95.     }
  96. }
  97.  
  98. void    UpdateFuseBalls()
  99. {
  100.     register    FuseBall    *fbp;
  101.     register    int            i,j;
  102.                 int            x,y,l;
  103.                 int            rd;    /*    A random number    */
  104.                 int            zap;    /* type of shot hit */
  105.     UpdateFuseOff();
  106.     
  107.     fbp=Balls;
  108.     for(i=0;i<MAXFUSEBALLS;i++)
  109.     {    if(fbp->activeflag)
  110.         {    if(fbp->mode<=0)
  111.             {    if(fbp->mode<0)
  112.                 {    fbp->lane=-(fbp->mode + 1)/STARDIVISION;
  113.                     fbp->sublane=0;
  114.                     fbp->mode=Warp;
  115.                     fbp->warplevel=(DEPTH<<4)/3;
  116.                     fbp->levelspeed=-WARPSPEED;
  117.                     fbp->lanespeed=0;
  118.                 }
  119.             }
  120.             else
  121.             {    rd=VARandom();
  122.                 if(fbp->mode==Edge)
  123.                     ThisLevel.edgeCount++;    /*    Fuseball is on the edge.            */
  124.                 switch(fbp->mode)
  125.                 {    case Waiting:    /*    Do nothing.    */
  126.                         break;
  127.                     case Warp:
  128.                         if(fbp->levelspeed<0)
  129.                         {    fbp->level += fbp->levelspeed;
  130.                             if(fbp->level < fbp->warplevel)
  131.                             {    
  132.                                 fbp->level= fbp->warplevel;
  133.                                 fbp->levelspeed=0;
  134.                                 fbp->mode=Brownian;
  135.                             }
  136.                         }
  137.                         else
  138.                         {    fbp->level += fbp->levelspeed;
  139.                             if(fbp->level > fbp->warplevel)
  140.                             {    fbp->level= fbp->warplevel;
  141.                                 fbp->levelspeed=0;
  142.                                 fbp->mode=Brownian;
  143.                             }
  144.                         }
  145.                         break;
  146.                     case Brownian:
  147. /* */                    if(ThisLevel.fuCount + (ThisLevel.lvNumber>>3) < ThisLevel.totalCount)
  148.                             fbp->level += fbp->levelspeed;
  149.                          else 
  150. /* */                     /* keep fuseballs moving up near end (mz)                */
  151.                             fbp->level+=(fbp->levelspeed > 0 )?-fbp->levelspeed:fbp->levelspeed;
  152.                         
  153.                         if(fbp->level>(DEPTH<<4)) /* if deeper than bottom 1/16 */
  154.                         {    fbp->level= (DEPTH<<4);
  155.                             if(fbp->levelspeed>0)
  156.                             {    fbp->levelspeed= - (fbp->levelspeed>>1);
  157.                             }
  158.                         }
  159.                         else
  160.                         if(fbp->level<=0)
  161.                         {    fbp->level=0;
  162.                             fbp->levelspeed=0;
  163. /* */                        if((ThisLevel.fuCount + (int)((ThisLevel.lvNumber)/8) >= ThisLevel.totalCount))
  164.                             {
  165.                                 fbp->mode=Edge; /* only have fuseballs on edge     */
  166.                                                 /*    after most else dead (mz)    */
  167.                             }
  168.                         }
  169.                         if(fbp->level>(DEPTH<<3)) /* if bottom 1/8 */
  170.                         {    fbp->levelspeed -= ((rd & 0x3000)>>12)-1;
  171.                         }
  172.                         else
  173.                         {    fbp->levelspeed += ((rd & 0x3000)>>12)-1;
  174.                         }
  175.                         if(fbp->levelspeed>MAXLEVELSPEED || fbp->levelspeed<=-MAXLEVELSPEED)
  176.                         {    fbp->levelspeed /= 3;
  177.                         }
  178.                         
  179.                         j=rd & 0xff;
  180.                         if(fbp->lane==Hero.lane) 
  181.                             j-= WARPANGER;
  182. #ifdef ZIMMER_WARP
  183.                         /* */
  184. /* */                    /* when # fuseballs = increasing percent remaining enemies     */
  185.                         /* make them more angry,so they bounce up and down more (mz)*/
  186.                         /* By mid-yellow they should be very active from the start     */
  187.                         /* */
  188.                         if((ThisLevel.fuCount + (int)(ThisLevel.lvNumber) - 16 >= ThisLevel.totalCount))
  189.                             {
  190.                                 /* Need to allow some sub-lane movement too while     */
  191.                                 /* mad so make anger somewhat random so they will    */
  192.                                 /* not go into warp, and will fall thru to sublane    */
  193.                                 /* code below.                                        */
  194.                                 /* */
  195.                                 if( (unsigned int)VARandom() > (unsigned int)((7*65536)/10))
  196.                                     j -= 5*WARPANGER; /* mz */
  197.                             }
  198.                         if(j<WARPPROB)
  199.                         {    
  200. /* */                        /* dont let fuseballs go into warp near the end so they    */
  201.                             /* will go to edge. (mz)                                */
  202.                             if((ThisLevel.fuCount + (ThisLevel.lvNumber>>3) - 1 < ThisLevel.totalCount))
  203.                                 fbp->mode=Warp;
  204.  
  205.                             j= (((unsigned int)VARandom()) % WARPRANGE) - WARPRANGE + (DEPTH<<4);
  206.                             if(j<0) j=0;
  207.                             if(j>(DEPTH<<4)) j=DEPTH<<4;
  208.                             if(j>fbp->level+MAXWARP)
  209.                             {    j=fbp->level+MAXWARP;
  210.                             }
  211.                             else
  212.                             if(j<fbp->level-MAXWARP)
  213.                             {    j=fbp->level-MAXWARP;
  214.                             }
  215.                             fbp->warplevel=j;
  216.                             fbp->levelspeed=(j<fbp->level)?-WARPSPEED:WARPSPEED;
  217.                         }
  218. #else
  219.                         if(j<WARPPROB)
  220.                         {    fbp->mode=Warp;
  221.                             j= (((unsigned int)VARandom()) % WARPRANGE) - WARPRANGE + (DEPTH<<4);
  222.                             if(j<0) j=0;
  223.                             if(j>(DEPTH<<4)) j=DEPTH<<4;
  224.                             if(j>fbp->level+MAXWARP)
  225.                             {    j=fbp->level+MAXWARP;
  226.                             }
  227.                             else
  228.                             if(j<fbp->level-MAXWARP)
  229.                             {    j=fbp->level-MAXWARP;
  230.                             }
  231.                             fbp->warplevel=j;
  232.                             fbp->levelspeed=(j<fbp->level)?-WARPSPEED:WARPSPEED;
  233.                         }
  234.  
  235. #endif
  236.                     case Edge:    /*    Fall through from Brownian too.    */
  237.                         fbp->sublane+=fbp->lanespeed;
  238.                         while(fbp->sublane<0)
  239.                         {    fbp->lane-=1;
  240.                             fbp->sublane+=LANEDIVISIONS;
  241.                         }
  242.  
  243.                         while(fbp->sublane >= LANEDIVISIONS)
  244.                         {    fbp->sublane-=LANEDIVISIONS;
  245.                             fbp->lane+=1;
  246.                         }
  247.                         
  248.                         if(fbp->lane<0)
  249.                         {    if(ww.wraps)
  250.                             {    fbp->lane+=ww.numsegs;
  251.                             }
  252.                             else
  253.                             {    fbp->lane=0;
  254.                                 fbp->sublane=0;
  255.                                 fbp->lanespeed= -fbp->lanespeed;
  256.                             }
  257.                         }
  258.                         else if(fbp->lane >= ww.numsegs)
  259.                         {    if(ww.wraps)
  260.                             {    fbp->lane -= ww.numsegs;
  261.                             }
  262.                             else
  263.                             {    fbp->lane--;
  264.                                 fbp->sublane+=LANEDIVISIONS-fbp->lanespeed;
  265.                                 fbp->lanespeed= -fbp->lanespeed;
  266.                             }
  267.                         }
  268.  
  269.                         fbp->lanespeed+=(rd & 8192)?-1:1;
  270.                         if(fbp->lanespeed>MAXLANESPEED || fbp->lanespeed<-MAXLANESPEED)
  271.                         {    fbp->lanespeed /=2;
  272.                         }
  273.                         break;
  274.                 }
  275.                 fbp->rotation+=ROTATIONSPEED;
  276.                 if(fbp->rotation>=ANGLES)    fbp->rotation-=ANGLES;
  277.                 
  278.                 l=fbp->level>>4;
  279.                 x=ww.x[fbp->lane][l];
  280.                 y=ww.y[fbp->lane][l];
  281.                 x += ((ww.x[fbp->lane+1][l]-x)*fbp->sublane)/LANEDIVISIONS;
  282.                 y += ((ww.y[fbp->lane+1][l]-y)*fbp->sublane)/LANEDIVISIONS;
  283.                 DrawFuseBall(x,y,ww.unitlen[l],fbp->rotation);
  284.                 
  285.                 /* Test for fuseball on edge of lane (fbp->lane)                */
  286.                 /* want to add test to allow player to pass thru fuseball         */
  287.                 /* as it changes lanes.                                             */
  288.                 /* So test to see if the fuseball is in the outer 8 sublanes     */
  289.                 /* if it is, then let the player pass thru by not adding the      */
  290.                 /* fusemaskto the lanstat (mz)                                     */
  291.                 /* eg 
  292.                 sublanes  0..7 8............................247 248....255 
  293.                            ^^^                 ^^^^                    ^^
  294.                            safe                    dead                  safe (mz) */
  295.                            
  296.                 if(    (l<FUSEDANGERLEVEL) && 
  297.                     (fbp->sublane>( (LANEDIVISIONS>>5) )) && 
  298.                     (fbp->sublane<(LANEDIVISIONS- (LANEDIVISIONS>>5) )) )
  299.                 {    Hero.lanestat[fbp->lane] |= FuseMask;
  300.                 } 
  301.                 
  302.                 /* fuseball can be shot if it is not in the outer 1/4 sublanes     */
  303.                 /* so it can be shot half of the time (mz)                         */
  304.                 
  305.                 if((fbp->sublane>( LANEDIVISIONS>>2) ) && 
  306.                     fbp->sublane<(LANEDIVISIONS-(LANEDIVISIONS>>2) ) ||
  307.                     Hero.superzapping)
  308.                 {    if(zap=ShotHitTest(fbp->lane,l))
  309.                     {    fbp->activeflag=0;
  310.                         NumBalls--;
  311.                         ThisLevel.fuCount--;
  312.                         ThisLevel.totalCount--;
  313.                                 
  314.                         /* have different score for Fuseballs depending upon     */
  315.                         /* how deeply they are killed (mz)     */
  316.                         /* do not show floating scores if superzap is used */
  317.                         
  318.                         if ( (DEPTH>l) && (l >= (int)(DEPTH*2/3)) )
  319.                         {        /* bottom 1/3 */
  320.                             IncreaseScore(ThisLevel.fuBullseye);
  321.                             if((PlayOptions->showfscores) && (zap != -2))
  322.                                 AddFLScore(x,y,ThisLevel.fuBullseye);
  323.                         }
  324.                         
  325.                         else if ( ((DEPTH*2/3)>l) && (l>=(int)(DEPTH/3)) )
  326.                         {        /* middle 1/3 */
  327.                             IncreaseScore(ThisLevel.fuPoints);
  328.                             if((PlayOptions->showfscores) && (zap != -2))
  329.                                 AddFLScore(x,y,(ThisLevel.fuPoints));
  330.                         }
  331.                         
  332.                         else
  333.                         {        /* upper 1/3 */
  334.                             IncreaseScore( (ThisLevel.fuPoints)>>1 );
  335.                             if((PlayOptions->showfscores) && (zap != -2))
  336.                                 AddFLScore(x,y,( (ThisLevel.fuPoints>>1) ));
  337.                         }
  338.                         
  339.                         BlowFuseBall(x,y,ww.unitlen[l],fbp->rotation);
  340.                         PlayB(Blow,11);
  341.                     }
  342.                 }
  343.             }
  344.         }
  345.         fbp++;
  346.     }
  347.     if(NumBalls<MAXFUSEBALLS && ThisLevel.fuCount>NumBalls)
  348.     {    if(VAPosRandom() < ThisLevel.fuProb+ThisLevel.probIncrease)
  349.         {    CreateNewBall();
  350.         }
  351.     }
  352.     ThisLevel.starCount += ThisLevel.fuCount-NumBalls;
  353.     ThisLevel.activeCount += NumBalls;
  354. }
  355. void    AllocFuseBalls()
  356. {
  357.     Balls=(FuseBall *)NewPtr(sizeof(FuseBall) * MAXFUSEBALLS);
  358.     NumBalls=0;
  359. }
  360.  
  361. void    InitFuseBalls()
  362. {
  363.     register    int        i;
  364.     
  365.     for(i=0;i<MAXFUSEBALLS;i++)
  366.     {    Balls[i].activeflag=0;
  367.     }
  368.     NumBalls=0;
  369. }
  370.